home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xpaint-2.1.1
/
rw
/
readWriteXWD.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
15KB
|
629 lines
/* +-------------------------------------------------------------------+ */
/* | Copyright 1993, David Koblas (koblas@netcom.com) | */
/* | | */
/* | Permission to use, copy, modify, and to distribute this software | */
/* | and its documentation for any purpose is hereby granted without | */
/* | fee, provided that the above copyright notice appear in all | */
/* | copies and that both that copyright notice and this permission | */
/* | notice appear in supporting documentation. There is no | */
/* | representations about the suitability of this software for | */
/* | any purpose. this software is provided "as is" without express | */
/* | or implied warranty. | */
/* | | */
/* +-------------------------------------------------------------------+ */
/*
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
#include "image.h"
#include <stdio.h>
#include <X11/XWDFile.h>
/*
** Some version of XWDFile.h don't have the 'typedef' infront of
** the XWDColor definition.
*/
typedef struct {
CARD32 pixel B32;
CARD16 red B16;
CARD16 green B16;
CARD16 blue B16;
CARD8 flags;
CARD8 pad;
} myXWDColor;
#define XWDColor myXWDColor
void *calloc(int, int);
#define True 1
#define False 0
#define LSBFirst 0
#define MSBFirst 1
#define XYBitmap 0
#define XYPixmap 1
#define ZPixmap 2
#define StaticGray 0
#define GrayScale 1
#define StaticColor 2
#define PseudoColor 3
#define TrueColor 4
#define DirectColor 5
#if XWD_FILE_VERSION != 7
*** This is an error ***
Do not know how to write anything but version 7 X window dumps
#endif
/*
** Some read and write routines for long values
*/
static unsigned long readlong(FILE *fp)
{
unsigned char a, b, c, d;
a = getc(fp);
b = getc(fp);
c = getc(fp);
d = getc(fp);
return ((a & 0xff) << 24) |
((b & 0xff) << 16) |
((c & 0xff) << 8) |
(d & 0xff);
}
static unsigned short readshort(FILE *fp)
{
unsigned char a, b;
a = getc(fp);
b = getc(fp);
return ((a & 0xff) << 8) | (b & 0xff);
}
static void writelong(FILE *fp, long l)
{
putc( (l >> 24) & 0xff, fp);
putc( (l >> 16) & 0xff, fp);
putc( (l >> 8) & 0xff, fp);
putc( l & 0xff, fp);
}
static void writeshort(FILE *fp, unsigned short s)
{
putc( (s >> 8) & 0xff, fp);
putc( s & 0xff, fp);
}
static long swaplong(long l)
{
unsigned char b1, b2, b3, b4;
b1 = (l >> 24) & 0xff;
b2 = (l >> 16) & 0xff;
b3 = (l >> 8) & 0xff;
b4 = l & 0xff;
return ((long)b4 << 24) | ((long)b3 << 16) | (b2 << 8) | b1;
}
static short swapshort(short l)
{
unsigned char b1, b2;
b1 = (l >> 8) & 0xff;
b2 = l & 0xff;
return (b2 << 8) | b1;
}
/*
**
*/
static int bits_per_item, bits_used, bit_shift, bits_per_pixel;
static unsigned long pixel_mask;
static int byte_order, bit_order;
static unsigned long getpixnum(FILE *fp)
{
static unsigned char b8;
static unsigned short b16;
static unsigned long b32;
unsigned long val;
if (bits_used == bits_per_item ) {
switch (bits_per_item) {
case 8:
b8 = getc(fp);
break;
case 16:
b16 = readshort(fp);
if (byte_order != MSBFirst)
b16 = swapshort(b16);
break;
case 32:
b32 = readlong(fp);
if (byte_order != MSBFirst)
b32 = swaplong(b32);
break;
}
bits_used = 0;
if (bit_order == MSBFirst)
bit_shift = bits_per_item - bits_per_pixel;
else
bit_shift = 0;
}
switch (bits_per_item) {
case 8:
val = (b8 >> bit_shift) & pixel_mask;
break;
case 16:
val = (b16 >> bit_shift) & pixel_mask;
break;
case 32:
val = (b32 >> bit_shift) & pixel_mask;
break;
}
if (bit_order == MSBFirst)
bit_shift -= bits_per_pixel;
else
bit_shift += bits_per_pixel;
bits_used += bits_per_pixel;
return val;
}
/*
** Straight forward writer.
** Take advantage of the fact that a Grey image is 8 bits deep
** and some simple properties of colormap images for simplicity.
*/
int WriteXWD(char *file, Image *image)
{
static char *name = "XPaint Image";
XWDColor color;
XWDFileHeader hdr;
FILE *fp;
int i, x, y;
int isBW = 0, isGrey = 0;
if ((fp = fopen(file, "w")) == NULL)
return True;
/*
** Set up the header.
*/
hdr.header_size = sizeof(hdr) + strlen(name) + 1;
hdr.file_version = XWD_FILE_VERSION;
hdr.pixmap_format = ZPixmap;
hdr.pixmap_width = image->width;
hdr.pixmap_height = image->height;
hdr.xoffset = 0;
hdr.byte_order = MSBFirst;
hdr.bitmap_bit_order = MSBFirst;
hdr.window_width = image->width;
hdr.window_height = image->height;
hdr.window_x = 0;
hdr.window_y = 0;
hdr.window_bdrwidth = 0;
if (image->isBW) {
hdr.pixmap_depth = 1;
hdr.bits_per_pixel = 1;
hdr.colormap_entries = image->cmapSize;
hdr.ncolors = image->cmapSize;
hdr.bytes_per_line = ( image->width + 7 ) / 8;
isBW = 1;
/*
** Common between grey and BW
*/
hdr.bitmap_unit = 8;
hdr.bitmap_pad = 8;
hdr.visual_class = StaticGray;
hdr.red_mask = 0;
hdr.green_mask = 0;
hdr.blue_mask = 0;
} else if (image->isGrey) {
hdr.pixmap_depth = 8;
hdr.bits_per_pixel = 8;
hdr.colormap_entries = image->cmapSize;
hdr.ncolors = image->cmapSize;
hdr.bytes_per_line = image->width;
isGrey = 1;
/*
** Common between grey and BW
*/
hdr.bitmap_unit = 8;
hdr.bitmap_pad = 8;
hdr.visual_class = StaticGray;
hdr.red_mask = 0;
hdr.green_mask = 0;
hdr.blue_mask = 0;
} else if (image->cmapSize > 0) {
/*
** Color mapped image
*/
hdr.pixmap_depth = (image->cmapSize > 256) ? 16 : 8;
hdr.bits_per_pixel = (image->cmapSize > 256) ? 16 : 8;
hdr.visual_class = PseudoColor;
hdr.colormap_entries = image->cmapSize;
hdr.ncolors = image->cmapSize;
hdr.red_mask = 0;
hdr.green_mask = 0;
hdr.blue_mask = 0;
hdr.bytes_per_line = image->width;
hdr.bitmap_unit = 8;
hdr.bitmap_pad = 8;
} else {
/*
** RGB Image
*/
hdr.pixmap_depth = 24;
hdr.bitmap_unit = 32;
hdr.bitmap_pad = 32;
hdr.bits_per_pixel = 32;
hdr.visual_class = DirectColor;
hdr.colormap_entries = 256;
hdr.ncolors = 0;
hdr.red_mask = 0xff0000;
hdr.green_mask = 0xff00;
hdr.blue_mask = 0xff;
hdr.bytes_per_line = image->width * 4;
}
hdr.bits_per_rgb = hdr.pixmap_depth;
/* Write out the header in big-endian order. */
writelong(fp, hdr.header_size );
writelong(fp, hdr.file_version );
writelong(fp, hdr.pixmap_format );
writelong(fp, hdr.pixmap_depth );
writelong(fp, hdr.pixmap_width );
writelong(fp, hdr.pixmap_height );
writelong(fp, hdr.xoffset );
writelong(fp, hdr.byte_order );
writelong(fp, hdr.bitmap_unit );
writelong(fp, hdr.bitmap_bit_order );
writelong(fp, hdr.bitmap_pad );
writelong(fp, hdr.bits_per_pixel );
writelong(fp, hdr.bytes_per_line );
writelong(fp, hdr.visual_class );
writelong(fp, hdr.red_mask );
writelong(fp, hdr.green_mask );
writelong(fp, hdr.blue_mask );
writelong(fp, hdr.bits_per_rgb );
writelong(fp, hdr.colormap_entries );
writelong(fp, hdr.ncolors );
writelong(fp, hdr.window_width );
writelong(fp, hdr.window_height );
writelong(fp, hdr.window_x );
writelong(fp, hdr.window_y );
writelong(fp, hdr.window_bdrwidth );
/*
** Write out the dump name.
*/
fwrite(name, 1, strlen(name) + 1, fp);
/*
** Write out the colormap, big-endian order.
*/
color.flags = 7;
color.pad = 0;
for ( i = 0; i < image->cmapSize; ++i ) {
color.pixel = i;
if (isBW) {
color.red = i * 65535L;
color.green = color.red;
color.blue = color.red;
} else if (isGrey) {
color.red = i << 8;
color.green = color.red;
color.blue = color.red;
} else {
color.red = image->cmapData[i * 3 + 0] << 8;
color.green = image->cmapData[i * 3 + 1] << 8;
color.blue = image->cmapData[i * 3 + 2] << 8;
}
writelong( fp, color.pixel );
writeshort( fp, color.red );
writeshort( fp, color.green );
writeshort( fp, color.blue );
(void)putc( color.flags, fp );
(void)putc( color.pad, fp );
}
/*
** Finally, write out the data.
*/
for (y = 0; y < image->height; y++) {
if (image->cmapSize == 0) {
/*
** Write RGB Image
*/
unsigned char *dp = &image->data[y * image->width * 3];
for (x = 0; x < image->width; x++) {
putc(0, fp);
putc(*dp, fp); dp++;
putc(*dp, fp); dp++;
putc(*dp, fp); dp++;
}
} else if (isBW) {
/*
** Write a B&W Image, which is 1 bit per pixel.
*/
unsigned char *dp = &image->data[y * image->width];
int v = 0, idx = 7;
for (x = 0; x < image->width; x++, dp++) {
v |= *dp << idx;
if (--idx < 0) {
idx = 7;
putc(v & 0xff, fp);
v = 0;
}
}
if (idx != 7)
putc(v & 0xff, fp);
} else if (image->cmapSize > 256) {
/*
** Write wide colormapped image
*/
unsigned short *dp = &((unsigned short *)image->data)[y * image->width];
for (x = 0; x < image->width; x++, dp++)
writeshort(fp, *dp);
} else {
/*
** Write normal colormapped image, which is also a Grey image
*/
unsigned char *dp = &image->data[y * image->width];
for (x = 0; x < image->width; x++, dp++)
putc(*dp, fp);
}
}
fclose(fp);
return False;
}
int TestXWD(char *file)
{
FILE *fd = fopen(file, "r");
long v;
if (fd == NULL)
return False;
readlong(fd);
v = readlong(fd);
fclose(fd);
return v == XWD_FILE_VERSION;
}
Image *ReadXWD(char *file)
{
int isGrey = True, isBW = False;
FILE *fp;
XWDFileHeader hdr;
Image *image = NULL;
unsigned char *ibp;
unsigned short *isp;
int i, x, y;
unsigned long red_mask, green_mask, blue_mask;
int byte_swap = False;
int scale, padright;
if ((fp = fopen(file, "r")) == NULL)
return NULL;
if (fread(&hdr, sizeof(hdr), 1, fp) != 1) {
fclose(fp);
return NULL;
}
if (swaplong(hdr.file_version) == XWD_FILE_VERSION) {
byte_swap = True;
hdr.header_size = swaplong( hdr.header_size );
hdr.file_version = swaplong( hdr.file_version );
hdr.pixmap_format = swaplong( hdr.pixmap_format );
hdr.pixmap_depth = swaplong( hdr.pixmap_depth );
hdr.pixmap_width = swaplong( hdr.pixmap_width );
hdr.pixmap_height = swaplong( hdr.pixmap_height );
hdr.xoffset = swaplong( hdr.xoffset );
hdr.byte_order = swaplong( hdr.byte_order );
hdr.bitmap_unit = swaplong( hdr.bitmap_unit );
hdr.bitmap_bit_order = swaplong( hdr.bitmap_bit_order );
hdr.bitmap_pad = swaplong( hdr.bitmap_pad );
hdr.bits_per_pixel = swaplong( hdr.bits_per_pixel );
hdr.bytes_per_line = swaplong( hdr.bytes_per_line );
hdr.visual_class = swaplong( hdr.visual_class );
hdr.red_mask = swaplong( hdr.red_mask );
hdr.green_mask = swaplong( hdr.green_mask );
hdr.blue_mask = swaplong( hdr.blue_mask );
hdr.bits_per_rgb = swaplong( hdr.bits_per_rgb );
hdr.colormap_entries = swaplong( hdr.colormap_entries );
hdr.ncolors = swaplong( hdr.ncolors );
hdr.window_width = swaplong( hdr.window_width );
hdr.window_height = swaplong( hdr.window_height );
hdr.window_x = swaplong( hdr.window_x );
hdr.window_y = swaplong( hdr.window_y );
hdr.window_bdrwidth = swaplong( hdr.window_bdrwidth );
} else if (hdr.file_version != XWD_FILE_VERSION) {
goto out;
}
/*
** Skip stored name
*/
for (i = 0; i < hdr.header_size - sizeof(hdr); ++i)
if (getc(fp) == EOF)
goto out;
/* Check whether we can handle this dump. */
if (hdr.pixmap_depth > 24)
goto out;
if (hdr.bits_per_rgb > 24)
goto out;
if (hdr.pixmap_format != ZPixmap && hdr.pixmap_depth != 1)
goto out;
if (hdr.bitmap_unit != 8 && hdr.bitmap_unit != 16 && hdr.bitmap_unit != 32)
goto out;
if (hdr.ncolors > 0) {
XWDColor *colors;
if ((colors = (XWDColor*)calloc(sizeof(XWDColor), hdr.ncolors)) == NULL)
goto out;
if (fread(colors, sizeof(XWDColor), hdr.ncolors, fp) != hdr.ncolors)
goto out;
image = ImageNewCmap(hdr.pixmap_width, hdr.pixmap_height, hdr.ncolors);
for (i = 0; i < hdr.ncolors; i++) {
unsigned char r, g, b;
if (byte_swap) {
colors[i].red = swapshort(colors[i].red);
colors[i].green = swapshort(colors[i].green);
colors[i].blue = swapshort(colors[i].blue);
}
r = colors[i].red >> 8;
g = colors[i].green >> 8;
b = colors[i].blue >> 8;
ImageSetCmap(image, i, r, g, b);
if (r != g || g != b)
isGrey = False;
}
if (isGrey && image->cmapData[0] == 0 && image->cmapData[3] == 255)
isBW = True;
} else {
/*
** RGB Image
*/
isGrey = False;
}
if (hdr.visual_class == TrueColor || hdr.visual_class == DirectColor) {
} else if (hdr.visual_class == StaticGray && hdr.bits_per_pixel == 1) {
/*
** B&W bitmap
*/
} else if (hdr.visual_class == StaticGray) {
}
switch (hdr.visual_class) {
case TrueColor:
case DirectColor:
image = ImageNew(hdr.pixmap_width, hdr.pixmap_height);
if (hdr.bits_per_pixel == 16)
scale = 4;
else
scale = 1;
break;
case StaticGray:
if (image != NULL)
break;
if (hdr.bits_per_pixel == 1) {
image = ImageNewBW(hdr.pixmap_width, hdr.pixmap_height);
} else {
image = ImageNewGrey(hdr.pixmap_width, hdr.pixmap_height);
scale = 256 / (1 << hdr.bits_per_pixel) - 1;
}
break;
default: /* StaticColor, PseudoColor, GrayScale */
if (image != NULL)
break;
image = ImageNew(hdr.pixmap_width, hdr.pixmap_height);
break;
}
padright = hdr.bytes_per_line * 8 / hdr.bits_per_pixel - hdr.pixmap_width;
bits_per_item = hdr.bitmap_unit;
bits_used = bits_per_item;
bits_per_pixel= hdr.bits_per_pixel;
byte_order = hdr.byte_order;
bit_order = hdr.bitmap_bit_order;
if ( bits_per_pixel == sizeof(pixel_mask) * 8 )
pixel_mask = -1;
else
pixel_mask = ( 1 << bits_per_pixel ) - 1;
red_mask = hdr.red_mask;
green_mask = hdr.green_mask;
blue_mask = hdr.blue_mask;
ibp = image->data;
isp = (unsigned short *)image->data;
for (y = 0; y < image->height; y++) {
switch (hdr.visual_class) {
case StaticGray:
case GrayScale:
case StaticColor:
case PseudoColor:
for (x = 0; x < image->width; x++) {
if (image->cmapSize > 256)
*isp++ = getpixnum(fp);
else if (image->isBW == 2)
*ibp++ = (getpixnum(fp) == 1) ? 0 : 1;
else
*ibp++ = getpixnum(fp);
}
break;
case TrueColor:
case DirectColor:
for (x = 0; x < image->width; x++) {
unsigned long ul = getpixnum(fp);
switch (hdr.bits_per_pixel) {
case 16:
*ibp++ = (ul & red_mask) >> 0;
*ibp++ = (ul & green_mask) >> 5;
*ibp++ = (ul & blue_mask) >> 10;
break;
case 24:
case 32:
*ibp++ = (ul & 0xff0000) >> 16;
*ibp++ = (ul & 0x00ff00) >> 8;
*ibp++ = (ul & 0x0000ff);
break;
}
}
}
for (x = 0; x < padright; x++)
getpixnum(fp);
}
out:
fclose(fp);
return image;
}